#pragma once
#include "2dMap.h"
struct Game
{	
	//Members
	Map map, piece;
	char input;

	//Functions

	//Constructors
	Game()	//Default constructor
	{

	}

	//Game loop functions
	void initialize()
	{
		srand((unsigned int)time(NULL));	//Seed the RNG
		map.loadFile("map.txt");
		piece.loadFile("tetrad3.txt");
		input = 0;
	}
	void draw()
	{
		map.draw();
		piece.draw();
		//Get piece's offset into map.
		int xOffset = piece.posX - map.posX;
		int yOffset = piece.posY - map.posY;
		//loop through piece//if you see a space, draw the corresponding character from a over it.
		for (int y = 0; y < piece.height; y++)
		{
			for (int x = 0; x < piece.width; x++)
			{
				if (piece.map[y][x] == ' ')
				{
					//if you see a space, draw the corresponding character from a over it.
					gotoxy(x + xOffset, y + yOffset);
					putchar(map.map[y + yOffset][x + xOffset]);
				}
			}
		}
	}
	char processInput()
	{
		enum ROTATION
		{
			NONE,
			CLOCKWISE,
			COUNTERCLOCKWISE
		};
		//Save the pieces previous position, in case we have to revert
		int oldX = piece.posX;
		int oldY = piece.posY;
		int rotation = NONE;	//0:  No rotation.  1:  left
		//Move the piece
		switch (input)
		{
		case 's': case 'S':
			{
				piece.posY++;
				break;
			}
		case 'a': case 'A':
			{
				piece.posX--;
				break;
			}
		case 'd': case 'D':
			{
				piece.posX++;
				break;
			}
		case 'e': case 'E':
			{
				piece.rotateCW();
				rotation = CLOCKWISE;
				break;
			}
		case 'q': case 'Q':
			{
				piece.rotateCCW();
				rotation = COUNTERCLOCKWISE;
				break;
			}
		default:	//Herpa Derpa...
			{
				break;
			}
		}
		//Make sure b stays within a's boundary
		if (piece.posX < map.posX /*Left Side*/ || 
			piece.posY < map.posY /*Top*/ ||
			piece.posX + piece.width > map.posX + map.width /*Right Side*/ ||
			piece.posY + piece.height > map.posY + map.height /*Bottom*/
			)
		{
			//The piece went out of bounds, so revert it.
			piece.posX = oldX;
			piece.posY = oldY;
			//It may have been rotated outside of the boundary.
			if (rotation != NONE)
			{
				if (rotation == CLOCKWISE)
				{
					piece.rotateCCW();
				}
				else
				{
					piece.rotateCW();
				}
			}
		}
		//Make piece static if it hits the bottom or another static piece
		if (piece.posY + piece.height >= map.posY + map.height/*Bottom*/)
		{
			copy('#');
			piece.posY = 0; piece.posX = 0;
			//Load a new piece and move it to the top
			if (!loadANewPiece())
			{
				gotoxy(map.width+1, 0);
				printf("Game Over");
				gotoxy(map.width+1, 1);
				return 27;
			}
		}
		if (collision('#','#')) //Falling piece hits a static piece
		{
			piece.posY = oldY;
			copy('#');
			piece.posY = 0; piece.posX = 0;
			//Load a new piece and move it to the top
			if (!loadANewPiece())
			{
				gotoxy(map.width+1, 0);
				printf("Game Over");
				gotoxy(map.width+1, 1);
				return 27;
			}
		}
		return 0;
	}
	char idleUpdate()
	{
		piece.posY++;
		//Make sure b stays within a's boundary
		if (piece.posX < map.posX /*Left Side*/ || 
			piece.posY < map.posY /*Top*/ ||
			piece.posX + piece.width > map.posX + map.width /*Right Side*/ ||
			piece.posY + piece.height > map.posY + map.height /*Bottom*/
			)
		{
			//The piece went out of bounds, so revert it.
			piece.posY--;
		}
		//Make piece static if it hits the bottom or another static piece
		if (piece.posY + piece.height > map.posY + map.height/*Bottom*/)
		{
			copy('#');
			piece.posX = 0;
			piece.posY = 0;
			//Load a new piece and move it to the top
			if (!loadANewPiece())
			{
				gotoxy(map.width+1, 0);
				printf("Game Over");
				gotoxy(map.width+1, 1);
				return 27;
			}

		}
		if (collision('#','#')) //Falling piece hits a static piece
		{
			piece.posY--;
			copy('#');
			piece.posX = 0;
			piece.posY = 0;
			//Load a new piece and move it to the top
			if (!loadANewPiece())
			{
				gotoxy(map.width+1, 0);
				printf("Game Over");
				gotoxy(map.width+1, 1);
				return 27;
			}

		}
		//check to see if a horizontal line should be cleared
		bool clearline = false;
		int horizontalCount = 0;
		int rowAbove = 0;
		//loop through the map, from row to row.
		for (int y = 0; y < map.height; y++)
		{
			for (int x = 0; x < map.width; x++)
			{
				if (map.map[y][x] == '#')
				{
					horizontalCount++;
				}
				if (horizontalCount == map.width)	//We found a whole row
				{
					rowAbove = y - 1;
					for (int x = 0; x < map.width; x++)
					{
						map.map[y][x] = '.';	//Clear it out
					}
					//loop through the map backwards, dropping every piece down
					for (int y = rowAbove; y >= 0; y--)
					{
						for (int x = map.width; x >= 0; x--)
						{
							map.map[y+1][x] = map.map[y][x];
						}
					}
				}
			}
			horizontalCount = 0;
		}
		return 0;
	}

	//Helper functions
	bool loadANewPiece()		//Returns true if it has space to load, false if the area is blocked.
	{
		int roll = rand() % 7 + 1;
		switch(roll)
		{
		case 1:
			{
				piece.loadFile("tetrad1.txt");
				break;
			}
		case 2:
			{
				piece.loadFile("tetrad2.txt");
				break;
			}
		case 3:
			{
				piece.loadFile("tetrad3.txt");
				break;
			}
		case 4:
			{
				piece.loadFile("tetrad4.txt");
				break;
			}
		case 5:
			{
				piece.loadFile("tetrad5.txt");
				break;
			}
		case 6:
			{
				piece.loadFile("tetrad6.txt");
				break;
			}
		case 7:
			{
				piece.loadFile("tetrad7.txt");
				break;
			}
		default:
			{
				break;
			}
		}
		if (collision('#','#'))
		{
			return false;
		}
		return true;
	}

	bool collision (char pieceTest, char mapTest)
	{
		int offX = piece.posX - map.posX;
		int offY = piece.posY - map.posY;
		int xA, yA;
		for (int yB = 0; yB < piece.height; ++yB)
		{
			for (int xB = 0; xB < piece.width; ++xB)
			{
				xA = xB + offX;
				yA = yB + offY;
				if (xA >= 0 && xA < map.width
					&& yA >= 0 && yA < map.height
					&& piece.map[yB][xB] == pieceTest
					&& map.map[yA][xA] == mapTest)
				{
					return true;
				}
			}
		}
		return false;
	}

	void copy(char toCopy)
	{
		int offX = piece.posX - map.posX;
		int offY = piece.posY - map.posY;
		int xA, yA;
		bool previousCopy = false;
		//Loop through once, to make sure there hasn't already been a copy to these positions
		for (int yB = 0; yB < piece.height; ++yB)
		{
			for (int xB = 0; xB < piece.width; ++xB)
			{
				xA = xB + offX;
				yA = yB + offY;
				if(map.map[yA][xA] == toCopy && piece.map[yB][yA] == toCopy)
				{
					previousCopy = true;
				}
			}
		}
		if (!previousCopy)
		{
			for (int yB = 0; yB < piece.height; ++yB)
			{
				for (int xB = 0; xB < piece.width; ++xB)
				{
					xA = xB + offX;
					yA = yB + offY;		
					if (xA >= 0 && xA < map.width
						&& yA >= 0 
						&& yA < map.height //Within boudaries
						&& piece.map[yB][xB] == toCopy)	//The character matches

					{
						map.map[yA][xA] = toCopy;
					}
				}
			}
		}
	}
};